package sqlDB

import (
	"fmt"
	"gitee.com/tsingeye/FreeEhome/config"
	"gitee.com/tsingeye/FreeEhome/tools"
	"gitee.com/tsingeye/FreeEhome/tools/logs"
	"github.com/astaxie/beego"
	"gorm.io/driver/mysql"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"os"
	"time"
)

var (
	gormDB *gorm.DB
	DBType string
)

func InitDB() {
	var err error
	//获取数据库类型
	DBType = beego.AppConfig.String("dbType")
	switch DBType {
	case "mysql", "sqlite3":
	default:
		DBType = "sqlite3"
		logs.BeeLogger.Emergency("init dbType error, set default dbType=%s", DBType)
	}

	//获取配置文件中的数据库名
	dbName := beego.AppConfig.String(tools.StringsJoin(DBType, "::dbName"))
	switch DBType {
	case "mysql":
		dbUser := beego.AppConfig.String(tools.StringsJoin(DBType, "::dbUser"))
		dbPwd := beego.AppConfig.String(tools.StringsJoin(DBType, "::dbPwd"))
		dbAddr := beego.AppConfig.String(tools.StringsJoin(DBType, "::dbAddr"))

		dsn := tools.StringsJoin(dbUser, ":", dbPwd, "@tcp(", dbAddr, ")/", "?charset=utf8mb4&parseTime=True&loc=Local")

		gormDB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
		if err != nil {
			logs.PanicLogger.Panicln(fmt.Sprintf("failed to connect %s database: %s", DBType, err))
		}
		//判断MySQL是否创建该数据库，若无则创建
		if err = gormDB.Exec(fmt.Sprintf("CREATE DATABASE if not exists `%s`", dbName)).Error; err != nil {
			logs.PanicLogger.Panicln("failed to create database error: ", err)
		}

		dsn = tools.StringsJoin(dbUser, ":", dbPwd, "@tcp(", dbAddr, ")/", dbName, "?charset=utf8mb4&parseTime=True&loc=Local")
		gormDB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
			//禁止AutoMigrate自动创建数据库外键约束
			DisableForeignKeyConstraintWhenMigrating: true,
		})
		if err != nil {
			logs.PanicLogger.Panicln(fmt.Sprintf("failed to connect %s database: %s", DBType, err))
		}
	case "sqlite3":
		//作为服务启动时需切换到当前工作目录
		os.Chdir(tools.GetAbsPath())
		gormDB, err = gorm.Open(sqlite.Open(dbName), &gorm.Config{
			//禁止AutoMigrate自动创建数据库外键约束
			DisableForeignKeyConstraintWhenMigrating: true,
		})
		if err != nil {
			logs.PanicLogger.Panicln(fmt.Sprintf("failed to connect %s database: %s", DBType, err))
		}

		//开启WAL模式，WAL模式支持读写并发，可有效防止数据库被锁
		if err := gormDB.Exec("PRAGMA journal_mode = wal").Error; err != nil {
			logs.PanicLogger.Panicln(fmt.Sprintf("failed to open PRAGMA journal_mode = wal error:%s", err))
		}
	}
	sqlDB, err := gormDB.DB()
	if err != nil {
		logs.PanicLogger.Panicln(fmt.Sprintf("init gorm.DB error: %s", err))
	}
	//SetMaxIdleConns 设置空闲连接池中连接的最大数量
	sqlDB.SetMaxIdleConns(10)
	//SetMaxOpenConns 设置打开数据库连接的最大数量。
	sqlDB.SetMaxOpenConns(100)
	//SetConnMaxLifetime 设置了连接可复用的最大时间。
	sqlDB.SetConnMaxLifetime(time.Hour)

	//设置不打印任何SQL语句
	//gormDB.Logger = gormDB.Logger.LogMode(logger.Silent)
	//设置打印详细的SQL语句
	gormDB.Logger = gormDB.Logger.LogMode(logger.Info)
	//gormDB.Logger = gormDB.Logger.LogMode(logger.Error)
	logs.BeeLogger.Emergency(fmt.Sprintf("successful connection to %s database", DBType))
	fmt.Printf("%s successful connection to %s database\n", time.Now().Format(config.TimeLayout), DBType)

	//初始化数据表
	initTable()
}
